home *** CD-ROM | disk | FTP | other *** search
- /*
- * librplay.c
- *
- * Copyright (c) 1992 by Mark Boyns
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation. This software is provided "as is" without express or
- * implied warranty.
- */
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <varargs.h>
- #include <malloc.h>
- #include <stdio.h>
- #include "version.h"
- #include "rplay.h"
-
- int rplay_errno;
-
- char *rplay_errlist[] = {
- "no error", /* RPLAY_ERROR_NONE */
- "out of memory", /* RPLAY_ERROR_MEMORY */
- "host not found", /* RPLAY_ERROR_HOST */
- "rplay service not found", /* RPLAY_ERROR_SERVICE */
- "cannot connect to socket", /* RPLAY_ERROR_CONNECT */
- "cannot create socket", /* RPLAY_ERROR_SOCKET */
- "unknown rplay attribute", /* RPLAY_ERROR_ATTRIBUTE */
- "error writing to socket", /* RPLAY_ERROR_WRITE */
- "error closing socket", /* RPLAY_ERROR_CLOSE */
- "append error", /* RPLAY_ERROR_APPEND */
- "max packet size exceeded", /* RPLAY_ERROR_PACKET_SIZE */
- "cannot enable broadcast", /* RPLAY_ERROR_BROADCAST */
- };
-
- /*
- * macro used to gradually increase an rplay buffer by COPY_SIZE bytes
- */
- #define COPY_SIZE 128
- #define COPY(rp, ptr, n) \
- rp->grow = 0; \
- while(rp->len + n > rp->size) { \
- rp->grow = 1; \
- rp->size += COPY_SIZE; \
- if (rp->size > MAX_PACKET) { \
- rplay_errno = RPLAY_ERROR_PACKET_SIZE; \
- return -1; \
- } \
- } \
- if (rp->grow) { \
- rp->buf = realloc(rp->buf, rp->size); \
- if (rp->buf == NULL) { \
- rplay_errno = RPLAY_ERROR_MEMORY; \
- return -1; \
- } \
- } \
- bcopy(ptr, rp->buf+rp->len, n); \
- rp->len += n; \
-
- /*
- * create an RPLAY instance
- */
- RPLAY *rplay_create()
- {
- RPLAY *rp;
-
- rplay_errno = RPLAY_ERROR_NONE;
-
- rp = (RPLAY *)malloc(sizeof(RPLAY));
- if (rp == NULL) {
- rplay_errno = RPLAY_ERROR_MEMORY;
- return NULL;
- }
- else {
- rp->len = 0;
- rp->buf = (char *)malloc(COPY_SIZE);
- if (rp->buf == NULL) {
- rplay_errno = RPLAY_ERROR_MEMORY;
- return NULL;
- }
- rp->size = COPY_SIZE;
- return rp;
- }
- }
-
- /*
- * free up memory used by rp
- */
- int rplay_destroy(rp)
- RPLAY *rp;
- {
- free(rp->buf);
- free(rp);
- }
-
- /*
- * set rplay attributes
- */
- int rplay_set(va_alist)
- va_dcl
- {
- va_list args;
- RPLAY *rp;
- char *p;
- unsigned char val, *valp = &val;
- int attr, append;
-
- rplay_errno = RPLAY_ERROR_NONE;
-
- va_start(args);
- rp = va_arg(args, RPLAY *);
- attr = va_arg(args, int);
-
- append = 0;
- switch(attr) {
- case RPLAY_APPEND_PLAY:
- if (rp->len <= 0 || rp->buf[0] != RPLAY_PLAY) {
- rplay_errno = RPLAY_ERROR_APPEND;
- return -1;
- }
- attr = RPLAY_PLAY;
- append = 1;
- break;
-
- case RPLAY_APPEND_PAUSE:
- if (rp->len <= 0 || rp->buf[0] != RPLAY_PAUSE) {
- rplay_errno = RPLAY_ERROR_APPEND;
- return -1;
- }
- attr = RPLAY_PAUSE;
- append = 1;
- break;
-
- case RPLAY_APPEND_STOP:
- if (rp->len <= 0 || rp->buf[0] != RPLAY_STOP) {
- rplay_errno = RPLAY_ERROR_APPEND;
- return -1;
- }
- attr = RPLAY_STOP;
- append = 1;
- break;
-
- case RPLAY_APPEND_CONTINUE:
- if (rp->len <= 0 || rp->buf[0] != RPLAY_CONTINUE) {
- rplay_errno = RPLAY_ERROR_APPEND;
- return -1;
- }
- attr = RPLAY_CONTINUE;
- append = 1;
- break;
-
- case RPLAY_APPEND_VOLUME_PLAY:
- if (rp->len <= 0 || rp->buf[0] != RPLAY_PLAY) {
- rplay_errno = RPLAY_ERROR_APPEND;
- return -1;
- }
- attr = RPLAY_VOLUME_PLAY;
- append = 1;
- break;
- }
-
- if (append) {
- rp->len--;
- }
- else {
- rp->len = 0;
- }
-
- switch(attr) {
- case RPLAY_PLAY:
- case RPLAY_PAUSE:
- case RPLAY_STOP:
- case RPLAY_CONTINUE:
- case RPLAY_VOLUME_PLAY:
- if (!append) {
- *valp = attr == RPLAY_VOLUME_PLAY ? RPLAY_PLAY : attr;
- COPY(rp, valp, 1);
- }
- for(;;) {
- p = va_arg(args, char *);
- if (p == NULL) {
- *valp = NULL;
- COPY(rp, valp, 1);
- break;
- }
- COPY(rp, p, strlen(p)+1);
- if (attr == RPLAY_VOLUME_PLAY) {
- *valp = (unsigned char)va_arg(args, int);
- COPY(rp, valp, 1);
- }
- else if (attr == RPLAY_PLAY) {
- *valp = RPLAY_DEFAULT_VOLUME;
- COPY(rp, valp, 1);
- }
- }
- break;
-
- default:
- rplay_errno = RPLAY_ERROR_ATTRIBUTE;
- return -1;
- }
-
- va_end(args);
-
- return 0;
- }
-
- /*
- * create a UDP socket for the given host
- */
- int rplay_open(host)
- char *host;
- {
- struct hostent *hp;
- #ifdef INETD
- struct servent *sp;
- #endif INETD
- int rplay_fd;
- u_long addr;
- struct sockaddr_in s;
- int on = 1;
-
- rplay_errno = RPLAY_ERROR_NONE;
-
- #ifdef INETD
- sp = getservbyname("rplay", "udp");
- if (sp == NULL) {
- rplay_errno = RPLAY_ERROR_SERVICE;
- return -1;
- }
- #endif INETD
-
- bzero(&s, sizeof(s));
-
- addr = inet_addr(host);
- if (addr == 0xffffffff) {
- hp = gethostbyname(host);
- if (hp == NULL) {
- rplay_errno = RPLAY_ERROR_HOST;
- return -1;
- }
- bcopy(hp->h_addr, &s.sin_addr.s_addr, hp->h_length);
- }
- else {
- bcopy(&addr, &s.sin_addr.s_addr, sizeof(addr));
- }
-
- #ifdef INETD
- s.sin_port = sp->s_port;
- #else
- s.sin_port = htons(RPLAY_PORT);
- #endif INETD
- s.sin_family = AF_INET;
-
- rplay_fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (rplay_fd < 0) {
- rplay_errno = RPLAY_ERROR_SOCKET;
- return -1;
- }
-
- if (connect(rplay_fd, &s, sizeof(s)) < 0) {
- rplay_errno = RPLAY_ERROR_CONNECT;
- return -1;
- }
-
- /*
- * enable broadcasting
- */
- if (setsockopt(rplay_fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
- rplay_errno = RPLAY_ERROR_BROADCAST;
- return -1;
- }
-
- return rplay_fd;
- }
-
- /*
- * write the RPLAY packet to the given socket descriptor
- */
- int rplay(rplay_fd, rp)
- int rplay_fd;
- RPLAY *rp;
- {
- rplay_errno = RPLAY_ERROR_NONE;
-
- if (write(rplay_fd, rp->buf, rp->len) != rp->len) {
- rplay_errno = RPLAY_ERROR_WRITE;
- return -1;
- }
-
- return 0;
- }
-
- /*
- * close the given rplay socket descriptor
- */
- int rplay_close(rplay_fd)
- int rplay_fd;
- {
- rplay_errno = RPLAY_ERROR_NONE;
-
- if (close(rplay_fd) < 0) {
- rplay_errno = RPLAY_ERROR_CLOSE;
- return -1;
- }
-
- return 0;
- }
-
- /*
- * report an rplay error to stderr
- */
- rplay_perror(s)
- char *s;
- {
- fprintf(stderr, "%s: %s\n", s, rplay_errlist[rplay_errno]);
- }
-